﻿using Styx;
using Styx.CommonBot;
using Styx.CommonBot.Routines;
using Styx.TreeSharp;
using Styx.WoWInternals;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Action = Styx.TreeSharp.Action;
using Styx.Helpers;
using Styx.Common;
using Styx.WoWInternals.WoWObjects;

namespace HelloWarrior
{
    public class Routine : CombatRoutine
    {

        private Composite _combat, _buffs;

        public override string Name { get { return "HelloWarrior"; } }
        public override WoWClass Class { get { return WoWClass.Warrior; } }
        public override Composite CombatBehavior { get { return _combat; } }
        public override Composite PreCombatBuffBehavior { get { return _buffs; } }
        public override Composite CombatBuffBehavior { get { return _buffs; } }
        private static LocalPlayer Me { get { return StyxWoW.Me; } }
        private static WoWUnit Target { get { return StyxWoW.Me.CurrentTarget; } }

        public override void Initialize() {
            _combat = CreateCombat();
            _buffs = CreateBuffs();
        }

        Composite CreateBuffs() {
            return new PrioritySelector(

                
                Cast("Battle Shout")

            );
        }

        Composite CreateCombat() {


            return new PrioritySelector(


                
                //Cast("Shockwave"),
                //Cast("Pummel"),

                //new Decorator(ret => Me.CurrentTarget.IsWithinMeleeRange,
                //    new PrioritySelector(

                Cast("Hamstring", ret => Target.IsWithinMeleeRange && ( !Target.HasAura("Hamstring") || getAuraTimeLeft("Hamstring", Target) <= 3 ) ),

                //Cast("Piercing Howl", ret => Target.Distance < 10 /*&& Target.IsPlayer*/ && !Target.HasAura("Piercing Howl") && !Target.HasAura("Hamstring")),

                Cast("Mortal Strike", ret => Target.IsWithinMeleeRange),

                Cast("Colossus Smash", ret => Target.IsWithinMeleeRange && getAuraTimeLeft("Colossus Smash", Target) <= 2),

                Cast("Execute", ret => Target.IsWithinMeleeRange),
                Cast("Overpower", ret => Target.IsWithinMeleeRange),

                Cast("Deadly Calm", ret => Target.IsWithinMeleeRange && getAuraStackCount("Taste for Blood") >= 3),

                Cast("Heroic Strike", ret => Target.IsWithinMeleeRange && hasAura("Taste for Blood") && getAuraTimeLeft("Taste for Blood") <= 2, false),
                Cast("Heroic Strike", ret => Target.IsWithinMeleeRange && hasAura("Deadly Calm") && Me.CurrentRage >= getAuraStackCount("Deadly Calm") * 20, false),

                Cast("Slam", ret => Target.IsWithinMeleeRange && Target.HealthPercent > 20 && Me.CurrentRage >= 70)

                /*
                Cast("Adrenaline Rush", ret => StyxWoW.Me.CurrentEnergy < 35),

                Cast("Blade Flurry", ret => !StyxWoW.Me.HasAura("Blade Flurry") && UnfriendlyUnits.Count() > 1),
                CancelAura("Blade Flurry", ret => StyxWoW.Me.HasAura("Blade Flurry") && UnfriendlyUnits.Count() <= 1),

                Cast("Revealing Strike", ret => !Target.HasAura("Revealing Strike")),
                Cast("Eviscerate", ret => StyxWoW.Me.ComboPoints == 5 || (Target.HealthPercent <= 30 && StyxWoW.Me.ComboPoints > 2)),
                Cast("Slice and Dice", ret => !StyxWoW.Me.HasAura("Slice and Dice")),
                Cast("Fan of Knives", ret => UnfriendlyUnits.Count() > 2),
                Cast("Sinister Strike")
                */
            );

        }

        public static TimeSpan GetSpellCooldown(string spell) {
            SpellFindResults sfr;
            if (SpellManager.FindSpell(spell, out sfr))
                return (sfr.Override ?? sfr.Original).CooldownTimeLeft;

            return TimeSpan.MaxValue;
        }

        public static double getAuraTimeLeft(string aura, WoWUnit u = null)
        {
            if (u == null)
            {
                u = StyxWoW.Me;
            }

            WoWAura wa = u.GetAuraByName(aura);
            return wa != null ? wa.TimeLeft.TotalSeconds : 0;

        }

        public static bool hasAura(string aura, WoWUnit u = null)
        {
            if (u == null)
            {
                u = StyxWoW.Me;
            }

            WoWAura wa = u.GetAuraByName(aura);
            return wa != null;

        }

        public static uint getAuraStackCount(string aura)
        {

            WoWAura wa = StyxWoW.Me.GetAuraByName(aura);
            return wa != null ? wa.StackCount : 0;

        }

        private delegate T Selection<out T>(object context);
        Composite Cast(string spell, Selection<bool> reqs = null, bool useGCD = true)
        {

            //Logging.Write(LogLevel.Normal, spell + ":" + GetSpellCooldown(spell));

            return
                new Decorator(
                    ret => ((reqs != null && reqs(ret)) || (reqs == null)) && SpellManager.CanCast(spell) && (!useGCD || !SpellManager.GlobalCooldown) && !StyxWoW.Me.IsCasting,
                    new Sequence(
                        //new Action(ret => Logging.Write(LogLevel.Normal, spell + " distance=" + Target.Distance)),
                        new Action(ret => SpellManager.Cast(spell))
                    )
                    
               );

        }




    }
}
